﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using AppDataStruct;
using System.Xml.Linq;
using LogLib;
using System.Drawing;

namespace EECMISWS
{
    public class CodeMapService
    {
        #region static field and functions

        private static object _lock = new object();
        protected static CodeMapService _instance;
        public static CodeMapService Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new CodeMapService();
                        }
                    }
                }
                return _instance;
            }
        }
        #endregion

        private string _xmlFile = "";

        public string BaseDirectory
        {
            get
            {
                return Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase).Substring(6);
            }
        }

        /// <summary>
        /// 最新错误信息
        /// </summary>
        public string Error { get; private set; }

        private XDocument _xmlDoc = null;

        private XElement _root = null;

        private Dictionary<string, List<CodeMap>> _dicSections = new Dictionary<string, List<CodeMap>>();

        private bool _bInited = false;
        public bool Inited
        {
            get { return _bInited; }
        }

        public CodeMapService()
        {
            _xmlFile = BaseDirectory + "\\DICTable\\CodeMap.xml";
        }

        private List<CodeMap> listXB = new List<CodeMap>();
        private List<CodeMap> listMZ = new List<CodeMap>();
        private List<CodeMap> listQWD = new List<CodeMap>();
        private List<CodeMap> listSQLB = new List<CodeMap>();
        private List<CodeMap> listGAQZZL = new List<CodeMap>();

        private List<CodeMap> listTWQZZL = new List<CodeMap>();
        private List<CodeMap> listBZLB = new List<CodeMap>();
        private List<CodeMap> listQSGX = new List<CodeMap>();
        private List<CodeMap> listQZFS = new List<CodeMap>();
        private List<CodeMap> listXXLY = new List<CodeMap>();

        private List<CodeMap> listKZDXLB = new List<CodeMap>();
        private List<CodeMap> listGXRLB = new List<CodeMap>();
        private List<CodeMap> listSFXY = new List<CodeMap>();
        private List<CodeMap> listQZYXCS = new List<CodeMap>();
        private List<CodeMap> listYXQ = new List<CodeMap>();

        private List<CodeMap> listCSD = new List<CodeMap>();
        private List<CodeMap> listZY = new List<CodeMap>();
        private List<CodeMap> listCJSY = new List<CodeMap>();

        private bool OpenXmlDOC()
        {
            if(!File.Exists(_xmlFile))
            {
                Error = string.Format("关键配置文件{0}不存在。", _xmlFile);
                Log.WriteAsync(Error);
                return false;
            }
            try
            {
                _xmlDoc = XDocument.Load(_xmlFile);
                _root = _xmlDoc.Element("ConfigSections");
                return true;
            }
            catch (Exception ex)
            {
                Error = string.Format("配置文件{0}加载错误:{1}", _xmlFile, ex.Message);
                Log.WriteException(ex.ToString());
                return false;
            }
        }

        #region Static Function
        public static T ParseConfigSection<T>(XElement e) where T : new()
        {
            Type type = typeof(T);
            T obj = new T();
            IEnumerable<XAttribute> atts = e.Attributes();
            string name = "", value = "";
            PropertyInfo propertyInfo = null;
            foreach (XAttribute att in atts)
            {
                name = att.Name.ToString();
                value = att.Value.Trim();
                propertyInfo = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
                if (propertyInfo != null)
                {
                    if (propertyInfo.PropertyType == typeof(string))
                    {
                        propertyInfo.SetValue(obj, value, null); //给对应属性赋值
                    }
                    else if (propertyInfo.PropertyType == typeof(bool) || propertyInfo.PropertyType == typeof(System.Boolean))
                    {
                        propertyInfo.SetValue(obj, Common.ConvertToBoolean(value, true), null); //给对应属性赋值
                    }
                    else if (propertyInfo.PropertyType == typeof(int))
                    {
                        propertyInfo.SetValue(obj, Common.ConvertToInt32(value, 120), null); //给对应属性赋值
                    }
                    else if (propertyInfo.PropertyType == typeof(Color))
                    {
                        propertyInfo.SetValue(obj, Common.GetColor(value), null); //给对应属性赋值(颜色)
                    }
                    else
                    {
                        propertyInfo.SetValue(obj, value, null); //给对应属性赋值
                    }
                }
                else
                {

                }
            }
            return obj;
        }

        public static List<T> GetConfigObject<T>(XElement root, string parentName) where T : new()
        {
            List<T> listOuts = new List<T>();
            XElement parent = root.Element(parentName);
            if (parent == null)
                return listOuts;
            string nodeName = typeof(T).Name;
            IEnumerable<XElement> elems = parent.Elements(nodeName);
            if (elems == null)
            {
                return listOuts;
            }
            if (elems.Count() == 0)
            {
                return listOuts;
            }
            try
            {
                Type type = typeof(T);
                foreach (XElement e in elems)
                {
                    T temp = ParseConfigSection<T>(e);
                    listOuts.Add(temp);
                }
                return listOuts;
            }
            catch (System.Exception ex)
            {
                Log.WriteException(ex.ToString());
                return listOuts;
            }
        }
        #endregion
        public bool LoadConfig()
        {
            if (!OpenXmlDOC())
            {
                return false;
            }     
            
            listBZLB = GetCodeMapSection(_root, "BZLB");
            listGAQZZL = GetCodeMapSection(_root, "GAQZZL");
            listMZ = GetCodeMapSection(_root, "MZ");
            listQSGX = GetCodeMapSection(_root, "QSGX");
            listQWD = GetCodeMapSection(_root, "QWD");

            listQZFS = GetCodeMapSection(_root, "QZFS");
            listXB = GetCodeMapSection(_root, "XB");
            listSQLB = GetCodeMapSection(_root, "SQLB");
            listTWQZZL = GetCodeMapSection(_root, "TWQZZL");
            listXXLY = GetCodeMapSection(_root, "XXLY");

            listKZDXLB = GetCodeMapSection(_root, "KZDXLB");
            listGXRLB = GetCodeMapSection(_root, "GXRLB");
            listQZYXCS = GetCodeMapSection(_root, "QZYXCS");
            listYXQ = GetCodeMapSection(_root, "YXQ");
            listSFXY = GetCodeMapSection(_root, "SFXY");

            listCSD = GetCodeMapSection(_root, "CSD");
            listZY = GetCodeMapSection(_root, "ZY");
            listCJSY = GetCodeMapSection(_root, "CJSY");
            _bInited = true;
            return true;
        }

        private List<CodeMap> GetCodeMapSection(XElement root, string parentName)
        {
            List<CodeMap> listOuts = GetConfigObject<CodeMap>(_root, parentName);
            if(!_dicSections.ContainsKey(parentName))
            {
                _dicSections.Add(parentName, listOuts);
            }
            return listOuts;
        }

        /// <summary>
        /// 通过code获取CodeMap的Value
        /// </summary>
        /// <param name="setion"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public string this[string setion, string code]
        {
            get
            {
                if (!_dicSections.ContainsKey(setion))
                {
                    return "";
                }             
                List<CodeMap> list = _dicSections[setion];
                if (list.FindIndex(r => r.Code.Equals(code)) >= 0)
                {
                    CodeMap map = list.Find(r => r.Code.Equals(code));
                    return map.Value;
                }
                else
                {
                    return "";
                }
            }
        }

        public string FindCode(string setion, string value)
        {
            if(string.IsNullOrEmpty(value))
            {
                return "";
            }
            if (!_dicSections.ContainsKey(setion))
            {
                return "";
            }
            if (setion == "CSD")
            {
                if (value.Contains("内蒙古"))
                {
                    value = "内蒙古";
                }
                else if (value.Contains("黑龙江"))
                {
                    value = "黑龙江";
                }
                else
                {
                    value = value.Substring(0, 2);
                }
            }
            List<CodeMap> list = _dicSections[setion];
            if (list.FindIndex(r => r.Value.Equals(value) || r.Value.Contains(value) || value.Contains(r.Value)) >= 0)
            {
                CodeMap map = list.Find(r => r.Value.Equals(value) || r.Value.Contains(value) || value.Contains(r.Value));
                return map.Code;
            }
            else
            {
                return "";
            }
        }
     
        public bool ContainsSection(string section)
        {
            return _dicSections.ContainsKey(section);
        }

        public bool ContainsCode(string section, string code)
        {
            if (_dicSections.ContainsKey(section))
            {
                if (_dicSections[section].FindIndex(r => r.Code.Equals(code)) >= 0)
                {
                    return true;
                }
            }
            return false;
        }

        public bool ContainsValue(string section, string value)
        {
            if (_dicSections.ContainsKey(section))
            {
                if (_dicSections[section].FindIndex(r => r.Value.Equals(value) || r.Value.Contains(value) || value.Contains(r.Value)) >= 0)
                {
                    return true;
                }
            }
            return false;
        }
    }
}
